package com.shengdong.water.code.utils


import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.*
import androidx.datastore.preferences.preferencesDataStore
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.shengdong.water.WaterApp
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.runBlocking
import java.io.IOException
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty

// 创建单例 DataStore
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "app_preferences")

object DataStoreUtil {
    val dataStore = WaterApp.instance.dataStore
    val gson = Gson()

    // 清除所有数据
    suspend fun clear() {
        dataStore.edit { it.clear() }
    }

    // 删除指定键的数据
    suspend fun remove(key: String) {
        dataStore.edit { it.remove(stringPreferencesKey(key)) }
    }

    // 同步获取值（仅在必要时使用）
    fun <T> getValue(key: Preferences.Key<T>, defaultValue: T): T {
        return runBlocking {
            dataStore.data
                .catch { e ->
                    if (e is IOException) {
                        emit(emptyPreferences())
                    } else {
                        throw e
                    }
                }
                .map { it[key] ?: defaultValue }
                .first()
        }
    }

    // 同步设置值（仅在必要时使用）
    fun <T> setValue(key: Preferences.Key<T>, value: T) {
        runBlocking {
            dataStore.edit { it[key] = value }
        }
    }

    // 异步获取值的 Flow
    private fun <T> getValueFlow(key: Preferences.Key<T>, defaultValue: T): Flow<T> {
        return dataStore.data
            .catch { e ->
                if (e is IOException) {
                    emit(emptyPreferences())
                } else {
                    throw e
                }
            }
            .map { it[key] ?: defaultValue }
    }

    // 字符串委托
    fun string(
        key: String? = null,
        defaultValue: String = ""
    ) = object : ReadWriteProperty<Any, String> {
        override fun getValue(thisRef: Any, property: KProperty<*>): String {
            val prefKey = stringPreferencesKey(key ?: property.name)
            return getValue(prefKey, defaultValue)
        }

        override fun setValue(thisRef: Any, property: KProperty<*>, value: String) {
            val prefKey = stringPreferencesKey(key ?: property.name)
            setValue(prefKey, value)
        }
    }

    // 字符串 Flow
    fun stringFlow(key: String, defaultValue: String = ""): Flow<String> {
        val prefKey = stringPreferencesKey(key)
        return getValueFlow(prefKey, defaultValue)
    }

    // 整数委托
    fun int(
        key: String? = null,
        defaultValue: Int = 0
    ) = object : ReadWriteProperty<Any, Int> {
        override fun getValue(thisRef: Any, property: KProperty<*>): Int {
            val prefKey = intPreferencesKey(key ?: property.name)
            return getValue(prefKey, defaultValue)
        }

        override fun setValue(thisRef: Any, property: KProperty<*>, value: Int) {
            val prefKey = intPreferencesKey(key ?: property.name)
            setValue(prefKey, value)
        }
    }

    // 整数 Flow
    fun intFlow(key: String, defaultValue: Int = 0): Flow<Int> {
        val prefKey = intPreferencesKey(key)
        return getValueFlow(prefKey, defaultValue)
    }

    // 长整数委托
    fun long(
        key: String? = null,
        defaultValue: Long = 0L
    ) = object : ReadWriteProperty<Any, Long> {
        override fun getValue(thisRef: Any, property: KProperty<*>): Long {
            val prefKey = longPreferencesKey(key ?: property.name)
            return getValue(prefKey, defaultValue)
        }

        override fun setValue(thisRef: Any, property: KProperty<*>, value: Long) {
            val prefKey = longPreferencesKey(key ?: property.name)
            setValue(prefKey, value)
        }
    }

    // 长整数 Flow
    fun longFlow(key: String, defaultValue: Long = 0L): Flow<Long> {
        val prefKey = longPreferencesKey(key)
        return getValueFlow(prefKey, defaultValue)
    }

    // 浮点数委托
    fun float(
        key: String? = null,
        defaultValue: Float = 0f
    ) = object : ReadWriteProperty<Any, Float> {
        override fun getValue(thisRef: Any, property: KProperty<*>): Float {
            val prefKey = floatPreferencesKey(key ?: property.name)
            return getValue(prefKey, defaultValue)
        }

        override fun setValue(thisRef: Any, property: KProperty<*>, value: Float) {
            val prefKey = floatPreferencesKey(key ?: property.name)
            setValue(prefKey, value)
        }
    }

    // 浮点数 Flow
    fun floatFlow(key: String, defaultValue: Float = 0f): Flow<Float> {
        val prefKey = floatPreferencesKey(key)
        return getValueFlow(prefKey, defaultValue)
    }

    // 布尔值委托
    fun boolean(
        key: String? = null,
        defaultValue: Boolean = false
    ) = object : ReadWriteProperty<Any, Boolean> {
        override fun getValue(thisRef: Any, property: KProperty<*>): Boolean {
            val prefKey = booleanPreferencesKey(key ?: property.name)
            return getValue(prefKey, defaultValue)
        }

        override fun setValue(thisRef: Any, property: KProperty<*>, value: Boolean) {
            val prefKey = booleanPreferencesKey(key ?: property.name)
            setValue(prefKey, value)
        }
    }

    // 布尔值 Flow
    fun booleanFlow(key: String, defaultValue: Boolean = false): Flow<Boolean> {
        val prefKey = booleanPreferencesKey(key)
        return getValueFlow(prefKey, defaultValue)
    }

    // 字符串集合委托
    fun stringSet(
        key: String? = null,
        defaultValue: Set<String> = emptySet()
    ) = object : ReadWriteProperty<Any, Set<String>> {
        override fun getValue(thisRef: Any, property: KProperty<*>): Set<String> {
            val prefKey = stringSetPreferencesKey(key ?: property.name)
            return getValue(prefKey, defaultValue)
        }

        override fun setValue(thisRef: Any, property: KProperty<*>, value: Set<String>) {
            val prefKey = stringSetPreferencesKey(key ?: property.name)
            setValue(prefKey, value)
        }
    }

    // 字符串集合 Flow
    fun stringSetFlow(key: String, defaultValue: Set<String> = emptySet()): Flow<Set<String>> {
        val prefKey = stringSetPreferencesKey(key)
        return getValueFlow(prefKey, defaultValue)
    }

    // 对象委托
    inline fun <reified T> obj(
        key: String? = null,
        defaultValue: T? = null
    ) = object : ReadWriteProperty<Any, T?> {
        override fun getValue(thisRef: Any, property: KProperty<*>): T? {
            val prefKey = stringPreferencesKey(key ?: property.name)
            val json = getValue(prefKey, "")
            if (json.isEmpty()) return defaultValue
            return try {
                gson.fromJson(json, T::class.java)
            } catch (e: Exception) {
                e.printStackTrace()
                defaultValue
            }
        }

        override fun setValue(thisRef: Any, property: KProperty<*>, value: T?) {
            val prefKey = stringPreferencesKey(key ?: property.name)
            if (value == null) {
                runBlocking { dataStore.edit { it.remove(prefKey) } }
            } else {
                setValue(prefKey, gson.toJson(value))
            }
        }
    }

    // 对象 Flow
    inline fun <reified T> objFlow(key: String, defaultValue: T? = null): Flow<T?> {
        val prefKey = stringPreferencesKey(key)
        return dataStore.data
            .catch { e ->
                if (e is IOException) {
                    emit(emptyPreferences())
                } else {
                    throw e
                }
            }
            .map {
                val json = it[prefKey] ?: ""
                if (json.isEmpty()) defaultValue
                else try {
                    gson.fromJson(json, T::class.java)
                } catch (e: Exception) {
                    e.printStackTrace()
                    defaultValue
                }
            }
    }

    // 列表委托
    inline fun <reified T> list(
        key: String? = null,
        defaultValue: List<T> = emptyList()
    ) = object : ReadWriteProperty<Any, List<T>> {
        override fun getValue(thisRef: Any, property: KProperty<*>): List<T> {
            val prefKey = stringPreferencesKey(key ?: property.name)
            val json = getValue(prefKey, "")
            if (json.isEmpty()) return defaultValue
            return try {
                gson.fromJson(json, object : TypeToken<List<T>>() {}.type)
            } catch (e: Exception) {
                e.printStackTrace()
                defaultValue
            }
        }

        override fun setValue(thisRef: Any, property: KProperty<*>, value: List<T>) {
            val prefKey = stringPreferencesKey(key ?: property.name)
            setValue(prefKey, gson.toJson(value))
        }
    }

    // 列表 Flow
    inline fun <reified T> listFlow(key: String, defaultValue: List<T> = emptyList()): Flow<List<T>> {
        val prefKey = stringPreferencesKey(key)
        return dataStore.data
            .catch { e ->
                if (e is IOException) {
                    emit(emptyPreferences())
                } else {
                    throw e
                }
            }
            .map {
                val json = it[prefKey] ?: ""
                if (json.isEmpty()) defaultValue
                else try {
                    gson.fromJson(json, object : TypeToken<List<T>>() {}.type)
                } catch (e: Exception) {
                    e.printStackTrace()
                    defaultValue
                }
            }
    }
}